package com.ruoyi.system.controller.standard;

import java.net.MalformedURLException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.TypeReference;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.common.utils.file.FileUtils;
import com.ruoyi.framework.config.ServerConfig;
import com.ruoyi.system.domain.standard_relevant.DataOperLog;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.system.domain.standard_relevant.DataFile;
import com.ruoyi.system.service.standard.IDataFileService;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.page.TableDataInfo;
import org.springframework.web.multipart.MultipartFile;

/**
 * 数据文件Controller
 *
 * @author ruoyi
 * @date 2024-07-19
 */
@RestController
@RequestMapping("/standards/dataFile")
public class DataFileController extends BaseController
{
    @Autowired
    private IDataFileService dataFileService;


    /**
     * 导出数据文件列表
     */
//    @PreAuthorize("@ss.hasPermi('standard:dataFile:export')")
    @Log(title = "导出数据文件列表", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, DataFile dataFile)
    {
        List<DataFile> list = dataFileService.selectDataFileList(dataFile);
        ExcelUtil<DataFile> util = new ExcelUtil<DataFile>(DataFile.class);
        util.exportExcel(response, list, "数据文件数据");
    }

    /**
     * 新增数据文件
     */
    @PreAuthorize("@ss.hasPermi('system:dataFile:add')")
    @Log(title = "新增数据文件", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody DataFile dataFile)
    {
        dataFile.setUserId(getUserId());
        dataFile.setDeptId(getDeptId());
        return toAjax(dataFileService.insertDataFile(dataFile));
    }




    /**
     * ----------------------------------------------------------------------------- 新的功能
     */
    /**
     * 1. 查询所有标准数据
     * 不用记录日志
     */
//    @PreAuthorize("@ss.hasPermi('standard:data:list')")
    @GetMapping("/all")
    public AjaxResult getAllDataFile()
    {
        return success(dataFileService.getAllDataFile());
    }

    /**
     * 2. 审核数据状态
     */
    @PreAuthorize("@ss.hasPermi('system:dataFile:audit')")
    @Log(title = "审核数据状态", businessType = BusinessType.AUDIT)
    @PutMapping("/audit/{id}/{newStatus}/{remark}")
    public AjaxResult auditDataStatus(@PathVariable("id") Long id, @PathVariable("newStatus") String newStatus,@PathVariable("remark") String remark)
    {
        Character new_status = newStatus.charAt(0);
        return toAjax(dataFileService.auditDataStatus(id, new_status,remark));
    }

    /**
     * 3. 查询数据文件列表  条件查询
     */
//    @PreAuthorize("@ss.hasPermi('system:dataFile:list')")
    @GetMapping("/list")
    public TableDataInfo list(DataFile dataFile)
    {
        startPage();
        List<DataFile> list = dataFileService.selectDataFileList(dataFile);
        return getDataTable(list);
    }

//    /**
//     * 4. 删除数据文件
//     */
//    @PreAuthorize("@ss.hasPermi('standard:dataFile:remove')")
//    @Log(title = "数据文件", businessType = BusinessType.DELETE)
//    @DeleteMapping("/{ids}")
//    public AjaxResult remove(@PathVariable Long[] ids)
//    {
//        return toAjax(dataFileService.deleteDataFileByIds(ids));
//    }

    /**
     * 5. 查询数据操作日志  by dataName
     */
    @PreAuthorize("@ss.hasPermi('system:dataFile:trace')")
    @GetMapping("/operLog/{dataName}")
    public AjaxResult getAllDataOperLog(@PathVariable String dataName)
    {
        List<DataOperLog> list = dataFileService.getAllDataOperLog(dataName);
        return AjaxResult.success(list);
    }

    /**
     * 6.  插入 数据操作日志
     */
//    @PreAuthorize("@ss.hasPermi('standard:data:add')")
    @PostMapping("/operLog")
    public AjaxResult insertDataOperLog(@RequestBody JSONObject data)
    {
        Long id = Long.parseLong("0");
        String operType = data.getString("operType");
        String dataName = data.getString("dataName");
        String content = data.getString("content");
        String operUser = data.getString("operUser");

        LocalDateTime nowTime = LocalDateTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String currentDateTime = nowTime.format(formatter);
        LocalDateTime parsedDateTime = LocalDateTime.parse(currentDateTime, formatter);
        Date operTime = java.sql.Timestamp.valueOf(parsedDateTime);

        DataOperLog dataOperLog = new DataOperLog(id, operType, dataName, content, operUser,operTime);
        return toAjax(dataFileService.insertDataOperLog(dataOperLog));
    }

    /**
     * 7.   上传文件-----Excel(单个)
     */
    @Autowired
    private ServerConfig serverConfig;

//    @PreAuthorize("@ss.hasPermi('system:dataFile:add')")
    @PostMapping("/uploadExcel")
    public AjaxResult uploadExcel(@RequestParam("file") MultipartFile file, HttpServletRequest data) throws Exception
    {
        try
        {
            /**
             * 上传excel 需要：
             * id(自增)，dataName(参数),status('2'),remark(参数),dataType('excel'),excelPath(url),standardCode(null),filesPath(null)
             */
            Long id = Long.parseLong("0");
            String dataName = data.getParameter("dataName");// 数据名称
            String remark = data.getParameter("remark");// 备注

            /**
             * 存文件 相关操作
             */
            String filePath = RuoYiConfig.getUploadPath()+'/'+"excel";
            String fileName = FileUploadUtils.upload(filePath, file);  // 上传并返回 新文件名称
            String url = serverConfig.getUrl() + fileName; // 真正可以下载的文件路径


            /**
             * 存入数据库
             */
            DataFile new_dataFile_excel = new DataFile(id, dataName, "2", remark,"excel",url, null, null, null, null);
            new_dataFile_excel.setUserId(getUserId());
            new_dataFile_excel.setDeptId(getDeptId());
            try{
                dataFileService.insertDataFile(new_dataFile_excel);
            }catch (Exception e){
                return AjaxResult.error(e.getMessage());
            }

            /**
             * 插入 数据操作日志 ---- 新增数据
             */
            String content ="{\"新增数据\": {\"after\": \""+dataName+"\", \"before\": \"\"}}";
            // 获取当前时间
            LocalDateTime nowTime = LocalDateTime.now();
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            String currentDateTime = nowTime.format(formatter);
            LocalDateTime parsedDateTime = LocalDateTime.parse(currentDateTime, formatter);
            Date now_time = java.sql.Timestamp.valueOf(parsedDateTime);
            DataOperLog dataOperLog = new DataOperLog(Long.parseLong("0"), "新增", dataName, content, "admin",now_time);
            try{
                dataFileService.insertDataOperLog(dataOperLog);
            }catch (Exception e){
                return AjaxResult.error(e.getMessage());
            }

            /**
             * 返回结果
             */
            AjaxResult ajax = AjaxResult.success();
            ajax.put("url", url);
            ajax.put("fileName", fileName);
            ajax.put("newFileName", FileUtils.getName(fileName));
            ajax.put("originalFilename", file.getOriginalFilename());
            return ajax;
        }
        catch (Exception e)
        {
            return AjaxResult.error(e.getMessage());
        }
    }

    /**
     * 7.   上传文件-----Supplement(单个)
     */
//    @PreAuthorize("@ss.hasPermi('system:dataFile:add')")
    @PostMapping("/uploadSupplement")
    public AjaxResult uploadSupplement(@RequestParam("file") MultipartFile file, HttpServletRequest data) throws Exception
    {
        try
        {
            /**
             *  是否为需要记录新增操作
             */
            boolean needRecord = false;

            /**
             * 上传supplement 需要:
             * id(自增)，dataName(参数),status('2'),remark(参数),dataType('supplement'),excelPath(null),standardCode(参数),filesPath(+=url)
             */
            Long id = Long.parseLong("0");
            String dataName = data.getParameter("dataName");// 数据名称
            String remark = data.getParameter("remark");// 备注
            String standardCode = data.getParameter("standardCode");// 标准号
            String indicator = data.getParameter("indicator");// 指标名称 -----  仅当dataType为supplement时有值

            /**
             * 存文件 相关操作
             */
            String filePath = RuoYiConfig.getUploadPath()+'/'+"supplement";
            String fileName = FileUploadUtils.upload(filePath, file);  // 上传并返回 新文件名称
            String url = serverConfig.getUrl() + fileName; // 真正可以下载的文件路径

            /**
             * 存入数据库时
             */
            /** 记录 indicator-filePath 的关系，后转为JSON 保存*/
            Map<String, List<String>> filesPathMap = new HashMap<>();
            DataFile dataFile = dataFileService.selectDataFileByDataName(dataName);

            /**
             * 第一次存   那就新增
             */
            if (dataFile == null) {
                needRecord = true;// 日志--新增数据
                List<String> urlList = new ArrayList<>();
                urlList.add(url);
                filesPathMap.put(indicator, urlList);
                JSONObject filesPath = new JSONObject(filesPathMap);
                DataFile new_dataFile_supplement = new DataFile(id, dataName, "2", remark, "supplement", null, standardCode, filesPath.toJSONString(),null,null);
                new_dataFile_supplement.setUserId(getUserId());
                new_dataFile_supplement.setDeptId(getDeptId());
                try {
                    dataFileService.insertDataFile(new_dataFile_supplement);
                } catch (Exception e) {
                    return AjaxResult.error(e.getMessage());
                }
            }/**
             *  非第一次存    更新 filesPath
             */
            else {
                String filesPath_Old = dataFile.getFilesPath();
                JSONObject filesPath_New = JSONObject.parseObject(filesPath_Old);

                if(filesPath_New.containsKey(indicator)){
                    List<String> urlList = filesPath_New.getJSONArray(indicator).toJavaList(String.class);
                    urlList.add(url);
                    filesPath_New.put(indicator, urlList);
                }else{
                    List<String> urlList = new ArrayList<>();
                    urlList.add(url);
                    filesPath_New.put(indicator, urlList);
                }
                DataFile update_dataFile_supplement = new DataFile(dataFile.getId(), dataName, "2", remark, "supplement", null, standardCode, filesPath_New.toJSONString(), dataFile.getUserId(), dataFile.getDeptId());
                try {
                    dataFileService.updateDataFile(update_dataFile_supplement);
                } catch (Exception e) {
                    return AjaxResult.error(e.getMessage());
                }
            }

            /**
             * 插入 数据操作日志 ---- 新增数据
             */
            if(needRecord){
                String content ="{\"新增数据\": {\"after\": \""+dataName+"\", \"before\": \"\"}}";
                // 获取当前时间
                LocalDateTime nowTime = LocalDateTime.now();
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                String currentDateTime = nowTime.format(formatter);
                LocalDateTime parsedDateTime = LocalDateTime.parse(currentDateTime, formatter);
                Date now_time = java.sql.Timestamp.valueOf(parsedDateTime);
                DataOperLog dataOperLog = new DataOperLog(Long.parseLong("0"), "新增", dataName, content, "admin",now_time);
                try{
                    dataFileService.insertDataOperLog(dataOperLog);
                }catch (Exception e){
                    return AjaxResult.error(e.getMessage());
                }
            }

            /**
             * 返回结果
             */
            AjaxResult ajax = AjaxResult.success();
            ajax.put("url", url);
            ajax.put("fileName", fileName);
            ajax.put("newFileName", FileUtils.getName(fileName));
            ajax.put("originalFilename", file.getOriginalFilename());
            return ajax;
        }
        catch (Exception e)
        {
            return AjaxResult.error(e.getMessage());
        }
    }

    /**
     * 8. 获取数据文件详细信息，下载会用到这个api
     */
    @PreAuthorize("@ss.hasPermi('system:dataFile:download')")
    @GetMapping(value = "/{id}")
    public AjaxResult getDataFileInfo(@PathVariable("id") Long id)
    {
        return AjaxResult.success(dataFileService.selectDataFileById(id));
    }
    /**
     * 9. 查询数据文件  by dataName
     */
//    @PreAuthorize("@ss.hasPermi('system:dataFile:list')")
    @PostMapping("/dataName")
    public AjaxResult getDataFileByName(@RequestBody String jsonData)
    {
        JSONObject jsonObject = JSON.parseObject(jsonData);
        String dataName = jsonObject.getString("dataName");

        return AjaxResult.success(dataFileService.selectDataFileByDataName(dataName));
    }

    /**
     * 10.  修改数据文件
     */
    @PreAuthorize("@ss.hasPermi('system:dataFile:edit')")
    @Log(title = "修改数据文件", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody DataFile dataFile)
    {
        return toAjax(dataFileService.updateDataFile(dataFile));
    }

    /**
     * 15. 修改备注 by id+dataName
     */
//    @PreAuthorize("@ss.hasPermi('system:dataFile:edit')")
    @PutMapping("/updateRemark/{id}/{remark}")
    public AjaxResult updateRemark(@PathVariable("id") Long id,@PathVariable("remark") String remark){
        return toAjax(dataFileService.updateRemark(id,remark));
    }

    /**
     * 11.  删除数据操作日志 by standardName
     */
//    @PreAuthorize("@ss.hasPermi('standard:data:remove')")
    @Log(title = "删除数据操作日志", businessType = BusinessType.DELETE)
    @DeleteMapping("/operLog/{dataName}")
    public AjaxResult deleteDataOperLogByDataName(@PathVariable String dataName)
    {
        return toAjax(dataFileService.deleteDataOperLogByDataName(dataName));
    }

    /**
     * 12. 删除数据 by id
     */

    /** 获取 url ---> 对应的本地文件存储路径
     *  使用时最好先在本地测试，看路径是否正确
     */
    String getTrueFilePath(String url, String dataType) {
        String basePath = RuoYiConfig.getUploadPath() + '/' + dataType;
        String dateFilePath = url.substring(url.indexOf('/'+dataType) + dataType.length() + 1);
        String trueFilePath = basePath + dateFilePath;

        /** 测试时，取消这些注释来判断是否可行     ！！！！！！！！！！！！*/
//        System.out.println("删除时，url " + url);
//        System.out.println("删除时，basePath " + basePath);
//        System.out.println("删除时，dateFilePath " + dateFilePath);
//        System.out.println("删除时，真实路径 " + trueFilePath);
        return trueFilePath;
    }

    /**
     *  根据 url ---> 获取文件名
     */
    String getFileName(String url){
        String fileName = url.substring(url.lastIndexOf('/') + 1);
        return fileName;
    }

    @PreAuthorize("@ss.hasPermi('system:dataFile:remove')")
    @Log(title = "删除数据", businessType = BusinessType.DELETE)
    @DeleteMapping("/{id}")
    public AjaxResult deleteDataById(@PathVariable Long id) throws MalformedURLException {
        // 获取该数据项
        DataFile dataToDelete = dataFileService.selectDataFileById(id);
        String dataType = dataToDelete.getDataType();
        /**
         * 删除具体的文件
         */
        if(dataType.equals("excel")) {
            // 删除文件
            String url = dataToDelete.getExcelPath();
            String trueFilePath = getTrueFilePath(url, dataType);
            FileUtils.deleteFile(trueFilePath);
        }else if(dataType.equals("supplement")){
            // 删除文件
            JSONObject filesPath = JSONObject.parseObject(dataToDelete.getFilesPath());
            for (String key : filesPath.keySet()) {
                List<String> urlList = filesPath.getJSONArray(key).toJavaList(String.class);
                for (String url : urlList) {
                    String trueFilePath = getTrueFilePath(url, dataType);
                    FileUtils.deleteFile(trueFilePath);
                }
            }
        }
        return toAjax(dataFileService.deleteDataFileById(id));
    }


    /**
     * 13. 修改数据 --- excel
     */
    @PreAuthorize("@ss.hasPermi('system:dataFile:edit')")
    @Log(title = "修改数据", businessType = BusinessType.UPDATE)
    @PostMapping("/updateExcel")
    public AjaxResult updateExcel(@RequestParam("file") MultipartFile file, HttpServletRequest data) throws Exception
    {
        try
        {
            /** 获取参数 */
            String previousUrl = data.getParameter("previousUrl");
            String dataType ="excel";
            String dataName = data.getParameter("dataName");

            /** 删除原文件 */
            String trueFilePath = getTrueFilePath(previousUrl, dataType);
            FileUtils.deleteFile(trueFilePath);

            /** 上传新文件 */
            String filePath = RuoYiConfig.getUploadPath()+'/'+"excel";
            String fileName = FileUploadUtils.upload(filePath, file);  // 上传并返回 新文件名称
            String newUrl = serverConfig.getUrl() + fileName; // 真正可以下载的文件路径
            /** 更新数据库 */
            DataFile excelToUpdate = dataFileService.selectDataFileByDataName(dataName);
            excelToUpdate.setExcelPath(newUrl);
            dataFileService.updateDataFile(excelToUpdate);

            /**
             * 插入 数据操作日志 ---- 文件修改
             */
            String previousFileName = getFileName(previousUrl);
            String newFileName = getFileName(newUrl);
            String content ="{\"修改文件\": {\"after\": \""+newFileName+"\", \"before\": \""+previousFileName+"\"}}";

            // 获取当前时间
            LocalDateTime nowTime = LocalDateTime.now();
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            String currentDateTime = nowTime.format(formatter);
            LocalDateTime parsedDateTime = LocalDateTime.parse(currentDateTime, formatter);
            Date now_time = java.sql.Timestamp.valueOf(parsedDateTime);
            DataOperLog dataOperLog = new DataOperLog(Long.parseLong("0"), "修改", dataName, content, "admin",now_time);
            dataFileService.insertDataOperLog(dataOperLog);
            /**
             * 返回结果
             */
            AjaxResult ajax = AjaxResult.success();
            ajax.put("url", newUrl);
            ajax.put("fileName", fileName);
            ajax.put("newFileName", FileUtils.getName(fileName));
            ajax.put("originalFilename", file.getOriginalFilename());
            return ajax;
        }
        catch (Exception e)
        {
            return AjaxResult.error("修改Excel文件失败",e.getMessage());
        }
    }

    /**
     * 13. 修改数据 --- supplement
     */
    @PreAuthorize("@ss.hasPermi('system:dataFile:edit')")
    @Log(title = "修改数据", businessType = BusinessType.UPDATE)
    @PostMapping("/updateSupplement")
    public AjaxResult updateSupplement(@RequestParam("file") MultipartFile file, HttpServletRequest data) throws Exception
    {
        try
        {
            /** 获取参数 */
            String previousUrl = data.getParameter("previousUrl");
            String dataType ="supplement";
            String dataName = data.getParameter("dataName");
            String indicator = data.getParameter("indicator");

            /** 删除原文件 */
            String trueFilePath = getTrueFilePath(previousUrl, dataType);
            FileUtils.deleteFile(trueFilePath);

            /** 上传新文件 */
            String filePath = RuoYiConfig.getUploadPath()+'/'+"supplement";
            String fileName = FileUploadUtils.upload(filePath, file);  // 上传并返回 新文件名称
            String newUrl = serverConfig.getUrl() + fileName; // 真正可以下载的文件路径

            /** 更新数据库 */
            DataFile supplementToUpdate = dataFileService.selectDataFileByDataName(dataName);
            JSONObject filesPath = JSONObject.parseObject(supplementToUpdate.getFilesPath());
            List<String> urlList = filesPath.getJSONArray(indicator).toJavaList(String.class);
            urlList.remove(previousUrl);
            urlList.add(newUrl);
            filesPath.put(indicator, urlList);
            supplementToUpdate.setFilesPath(filesPath.toJSONString());
            dataFileService.updateDataFile(supplementToUpdate);

            /**
             * 插入 数据操作日志 ---- 文件修改
             */
            String previousFileName = getFileName(previousUrl);
            String newFileName = getFileName(newUrl);
            String content ="{\"修改文件\": {\"after\": \""+newFileName+"\", \"before\": \""+previousFileName+"\"}}";

            // 获取当前时间
            LocalDateTime nowTime = LocalDateTime.now();
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            String currentDateTime = nowTime.format(formatter);
            LocalDateTime parsedDateTime = LocalDateTime.parse(currentDateTime, formatter);
            Date now_time = java.sql.Timestamp.valueOf(parsedDateTime);
            DataOperLog dataOperLog = new DataOperLog(Long.parseLong("0"), "修改", dataName, content, "admin",now_time);
            dataFileService.insertDataOperLog(dataOperLog);

            /**
             * 返回结果
             */
            AjaxResult ajax = AjaxResult.success();
            ajax.put("url", newUrl);
            ajax.put("fileName", fileName);
            ajax.put("newFileName", FileUtils.getName(fileName));
            ajax.put("originalFilename", file.getOriginalFilename());
            return ajax;
        }
        catch (Exception e)
        {
            return AjaxResult.error("修改supplement失败",e.getMessage());
        }
    }


    /**
     * 14. 合并 filesPath by standardCode
     */
//    @PreAuthorize("@ss.hasPermi('standard:dataFile:list')")
    @GetMapping("/mergeFilesPath/{standardCode}")
    public AjaxResult mergeFilesPathByCode(@PathVariable String standardCode)
    {
        List<Map<String,Object>> filesPathList = dataFileService.mergeFilesPathByCode(standardCode);

        // 合并相同指标的文件路径
        Map<String, List<String>> mergedFilesPath = new HashMap<>();
        ObjectMapper objectMapper = new ObjectMapper();
        for (Map<String, Object> filesPath : filesPathList) {
            String filePathJson = (String) filesPath.get("files_path");
            try {
                Map<String, Object> filePathMap = objectMapper.readValue(filePathJson, Map.class);
                for (Map.Entry<String, Object> entry : filePathMap.entrySet()) {
                    String key = entry.getKey();
                    List<String> values = (List<String>) entry.getValue();
                    if (mergedFilesPath.containsKey(key)) {
                        mergedFilesPath.get(key).addAll(values);
                    } else {
                        mergedFilesPath.put(key, values);
                    }
                }
            }  catch (JsonMappingException e ) {
                throw new RuntimeException(e);
            } catch (JsonProcessingException e) {
                throw new RuntimeException(e);
            }
        }
        return AjaxResult.success(mergedFilesPath);
    }

}
